package eval.utilities.random;

import cern.jet.random.AbstractDistribution;
import cern.jet.random.Normal;
import cern.jet.random.Poisson;
import cern.jet.random.Uniform;
import cern.jet.random.engine.MersenneTwister;
import cern.jet.random.engine.RandomEngine;
import eval.utilities.configuration.ExperimentConfiguration;

/**
 * This class is used to generate Random distribution.
 * 
 * @author Nicolo' M. Calcavecchia <calcavecchia@elet.polimi.it>
 * @author Amit Peled   <amit.kapina@gmail.com>
 * @author Igal Kaufman <igal.kaufman@gmail.com>
 */

public class RandomUtilities {

	private static final ExperimentConfiguration conf = ExperimentConfiguration.getSingleton();

	private RandomEngine randomEngine = null;

	private Uniform uniformDistribution = null;

	private Normal normalDistribution = null;

	private Poisson poissonDistribution = null;


	/**
	 * Uniform Distribution
	 * 
	 * @return Uniform Distribution
	 */
	public  Uniform getNewUniformDistribution() {
		return new Uniform(getNewRandomEngine());
	}

	/**
	 * Uniform Distribution
	 * 
	 * @param min
	 * @param max
	 * @return Uniform
	 */
	public  Uniform getNewUniformDistribution(double min, double max) {
		return new Uniform(min, max, getNewRandomEngine());
	}

	/**
	 * Poison Distribution
	 * 
	 * @param average
	 * @return Poison Distribution
	 */
	public Poisson getNewPoissonDistribution(double average) {
		return new Poisson(average, getNewRandomEngine());
	}

	/**
	 * Returns a random number between 0 and 1 extracted from a uniform
	 * distribution
	 * 
	 * @return distribution between 0 and 1 
	 */
	public double generateNewRandomNumber() {
		if (uniformDistribution == null)
			uniformDistribution = getNewUniformDistribution();
		return uniformDistribution.nextDouble();
	}

	/**
	 * Generate new random engine
	 * 
	 * @return Random engine
	 */
	public RandomEngine getNewRandomEngine() {
		if (randomEngine == null) {
			randomEngine = new MersenneTwister(conf.randomSeed);
		}
		return randomEngine;
	}

	/**
	 * Normal Distribution
	 * 
	 * @param mean
	 * @param std
	 * @return Normal Distribution
	 */
	public Normal getNewNormalDistribution(int mean, double std) {
		return new Normal(mean, std, getNewRandomEngine());
	}

	/**
	 * Constant Distribution
	 * 
	 * @param average
	 * @return Constant Distribution
	 */
	public AbstractDistribution getNewConstantDistribution(int average) {
		return new ConstantDistribution(average);
	}

}
